using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace JH
{
    public class Mono : MonoBehaviour
    {
        private int _mainThreadId;
        private float _timer;

        private async void Awake()
        {
            _mainThreadId = Thread.CurrentThread.ManagedThreadId;
            Debug.Log("主线程ID:\t" + _mainThreadId);
            var task = TestReturnJTaskT();
            var value = await task; // 不能将void 转换为var
            Debug.Log(value);
            await TestReturnJTask();
        }
        
        private async JTask TestReturnJTask()
        {
            Debug.Log("TestReturnJTask 测试返回JTask " + LogThreadID + " " + LogTime);
            await JTask.WaitForSeconds(1);
            Debug.Log("TestReturnJTask 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
        }

        private async JTask<int> TestReturnJTaskT()
        {
            Debug.Log("TestReturnJTaskT 测试返回JTask " + LogThreadID + " " + LogTime);
            await JTask.WaitForSeconds(1);
            Debug.Log("TestReturnJTaskT 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
            return 999999;
        }

        private async Task Test()
        {
            Debug.Log("Test 测试返回主线程 " + LogThreadID + " " + LogTime);
            await JTask.SwitchToMainThread();
            Debug.Log("Test 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
        }

        private async Task Test2()
        {
            Debug.Log("Test2 测试等待直到条件满足：条件为延时3秒" + LogThreadID + " " + LogTime);
            var startTime = DateTime.Now;
            await JTask.WaitUntil(() => (DateTime.Now - startTime).TotalSeconds >= 3);
            Debug.Log("Test2 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
        }

        private async Task Test3()
        {
            Debug.Log("Test3 测试等待5秒" + LogThreadID + " " + LogTime);
            await JTask.WaitForSeconds(5);
            Debug.Log("Test3 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
        }

        private async void TestWhenAny()
        {
            Debug.Log("WhenAny 测试" + LogThreadID + " " + LogTime);
            var task1 = Test();
            var task2 = Test2();
            var task3 = Test3();
            await Task.WhenAny(task1, task2, task3);
            Debug.Log("WhenAny 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
        }

        private async void TestWhenAll()
        {
            Debug.Log("WhenAll 测试" + LogThreadID + " " + LogTime);
            Task task1 = Test();
            Task task2 = Test2();
            Task task3 = Test3();
            var waitAll = Task.WhenAll(task1, task2, task3);
            await waitAll;
            Debug.Log("WhenAll 执行完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
        }

        private async void TestCancel()
        {
            try
            {
                Debug.Log(" TestCancel 测试" + LogThreadID + " " + LogTime);
                var source = new CancellationTokenSource();
                var cancelTask = Task.Run(async () =>
                {
                    Debug.Log("TestCancel 开始等待1秒后取消" + LogThreadID + " " + LogTime);
                    await JTask.WaitForSeconds(1, source.Token);
                    Debug.Log("TestCancel 等待完毕 " + LogThreadID + " " + LogEqualThread + " " + LogTime);
                    source.Cancel();
                    Debug.Log("已取消token");
                });
                await JTask.WaitForSeconds(3, source.Token);
                Debug.Log("TestCancel 执行完毕 [这里不该被执行！]" + LogThreadID + " " + LogEqualThread + " " + LogTime);
            }
            catch (OperationCanceledException)
            {
                Debug.Log("TestCancel 取消 " + LogThreadID + " " + LogTime);
            }
        }

        private string LogThreadID => "当前线程ID " + Thread.CurrentThread.ManagedThreadId;
        private string LogTime => "当前时间 " + DateTime.Now.ToString("hh:mm:ss");
        private string LogEqualThread => "是否和主线程ID相同 " + (Thread.CurrentThread.ManagedThreadId == _mainThreadId);
    }
}